package com.beans;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import org.primefaces.event.TransferEvent;
import org.primefaces.model.DualListModel;

import model.Projection;
import model.Seat;
import model.User;

import com.Constants;
import com.services.ProjectionsService;
import com.util.DummyDataHolder;

@ManagedBean(name = "projectionBean")
@SessionScoped
/**
 * serves for view the project, reserve seats, marking seats as attended
 * 
 * @author kaloyan
 *
 */
public class ProjectionBean implements Serializable {

	@EJB
	ProjectionsService service;

	private Projection projection;

	private final int seatsPerRow = 5;

	private final String[] rowsAlphabet = { "A", "B", "C", "D", "E", "F" };

	private List<DummyDataHolder> seats;

	private DummyDataHolder selectedSeat;

	/**
	 * list usernames of users who bought seats
	 */
	private DualListModel<String> users;

	@ManagedProperty(value = "#{UserSessionBean}")
	private UserSessionBean userSessionBean;

	/**
	 * fancy indexing seats from each row using the DummyDataHolder data model
	 * 
	 * @return
	 */
	public List<DummyDataHolder> getSeats() {

		List<Seat> seatsFromDb = service.getSeatsByProjectionId(this.projection
				.getId());

		this.seats = new ArrayList<DummyDataHolder>();

		int currentRow = 0;

		for (int i = 0; i < seatsFromDb.size(); i++) {
			if (i != 0 && i % 10 == 0) {
				currentRow++;
			}

			int digit = i + 1 - (currentRow * this.seatsPerRow);

			DummyDataHolder dummyDataHolder = new DummyDataHolder(digit,
					seatsFromDb.get(i));

			seats.add(dummyDataHolder);

		}

		return this.seats;
	}

	public void setSeats(List<DummyDataHolder> seats) {
		this.seats = seats;
	}

	public Projection getProjection() {
		return projection;
	}

	public void setProjection(Projection projection) {
		this.projection = projection;
	}

	public String[] getRowsAlphabet() {
		return rowsAlphabet;
	}

	public DummyDataHolder getSelectedSeat() {
		return selectedSeat;
	}

	/**
	 * when seat(button from the grid) is clicked is setter is invoked and
	 * commit update in db the whole page is reloaded and datagrid is refreshed
	 * 
	 * @param selectedSeat
	 *            the clicked button (using setPropertyActionListener to map the
	 *            seat with the bean)
	 */
	public void setSelectedSeat(DummyDataHolder selectedSeat) {

		try {

			if (this.userSessionBean.getUser().getRole().equals(Constants.USER)) {

				this.service.switchLockOfSeat(selectedSeat.getSeat().getId(),
						this.userSessionBean.getUser());

			} else {

				this.service.switchAttendanceOfSeat(selectedSeat.getSeat()
						.getId());

			}

		} catch (NullPointerException e) {

			FacesContext.getCurrentInstance().addMessage(
					null,
					new FacesMessage(FacesMessage.SEVERITY_WARN,
							"Seat does not exists!", "Please Try Again!"));

		}

		this.selectedSeat = selectedSeat;
	}

	public void payForSeats() {
		List<Seat> seatsToPayForList = new ArrayList<Seat>();

		for (DummyDataHolder dh : this.seats) {
			if (dh.isLocked()
					&& !dh.getSeat().isSold()
					&& dh.getSeat().getUser().getId() == this.userSessionBean
							.getUser().getId()) {
				seatsToPayForList.add(dh.getSeat());
			}
		}
		this.service.payForSeats(seatsToPayForList,
				this.userSessionBean.getUser());
	}

	public UserSessionBean getUserSessionBean() {
		return userSessionBean;
	}

	public void setUserSessionBean(UserSessionBean userSessionBean) {
		this.userSessionBean = userSessionBean;
	}

	public int getSeatsPerRow() {
		return seatsPerRow;
	}

	public DualListModel<String> getUsers() {

		if (this.users == null) {

			this.users = new DualListModel<String>();

			List<User> allUsersWhoBought = service
					.getUsersWhoBoughtSeats(this.projection.getId());

			List<User> usersWhoAttended = service
					.getUsersWhoAttendedProjection(this.projection.getId());

			for (int i = 0; i < usersWhoAttended.size(); i++) {

				allUsersWhoBought.remove(usersWhoAttended.get(i));

			}

			this.users.setSource(new ArrayList<String>());
			this.users.setTarget(new ArrayList<String>());

			for (int i = 0; i < allUsersWhoBought.size(); i++) {

				this.users.getSource().add(
						allUsersWhoBought.get(i).getUserName());

			}

			for (int i = 0; i < usersWhoAttended.size(); i++) {

				this.users.getTarget().add(
						usersWhoAttended.get(i).getUserName());

			}

		}

		return this.users;
	}

	public void setUsers(DualListModel<String> users) {
		// setera mu se izvikva kato cakne submit

		this.users = users;

		List<String> attended = this.users.getTarget();

		List<String> noAttended = this.users.getSource();

		for (int i = 0; i < attended.size(); i++) {

			this.service.setAttendanceOfSeats(attended.get(i), true);
		}

		for (int i = 0; i < noAttended.size(); i++) {

			this.service.setAttendanceOfSeats(noAttended.get(i), false);
		}

	}

	public void onTransfer(TransferEvent event) {
		StringBuilder builder = new StringBuilder();
		for (Object item : event.getItems()) {
			builder.append(((String) item)).append("<br />");
		}

		FacesMessage msg = new FacesMessage();
		msg.setSeverity(FacesMessage.SEVERITY_INFO);
		msg.setSummary("Items Transferred");
		msg.setDetail(builder.toString());

		FacesContext.getCurrentInstance().addMessage(null, msg);

	}

}
